﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace EcoSystem.Office.Excel
{


    /// <summary>
    /// 
    /// </summary>
    public class ExcelExportOptions : ExcelExportOptions<object>
    {

    }

    /// <summary>
    /// Excel导出选项定义类
    /// </summary>
    public class ExcelExportOptions<T> where T : class
    {
        /// <summary>
        /// 是否绘制边框
        /// </summary>
        public bool DrawCellBorder { get; set; }

        /// <summary>
        /// 行高
        /// </summary>
        public int RowHeight { get; set; }

        /// <summary>
        /// 是否自动设置列宽
        /// </summary>
        public bool AutoSizeColumn { get; set; }

        /// <summary>
        /// 默认日期格式处理
        /// </summary>
        public string DateTimeFormatter { get; set; } = "yyyy年MM月dd日 HH:mm";

        /// <summary>
        /// 
        /// </summary>
        public string SheetName { get; set; } = "Sheet1";

        /// <summary>
        /// 标题
        /// </summary>
        public string Caption { get; set; }

        /// <summary>
        /// 自定义头部行数据
        /// </summary>
        public List<HeaderRow> HeaderRows { get; set; }

        /// <summary>
        /// 是否影藏列标题行
        /// </summary>
        public bool HideColumnTitleRow { get; set; } = false;

        /// <summary>
        /// 导出列配置
        /// </summary>
        public List<ExportColumn> Columns { get; set; }

        /// <summary>
        /// 页脚
        /// </summary>
        public string FooterContent { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public ExcelExportOptions()
        {
            this.Columns = new List<ExportColumn>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <param name="caption"></param>
        /// <param name="validate"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public ExcelExportOptions<T> AddColumn(Expression<Func<T, object>> item, string caption, CellValidate validate = null, int width = 0)
        {
            string fieldName = GetPropertyName(item);
            var dataType = GetPropertyType(item);
            this.Columns.Add(new ExportColumn()
            {
                FieldName = fieldName,
                Caption = caption,
                DataType = dataType,
                Validate = validate,
                Width = width
            });
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="dataType"></param>
        /// <param name="validate"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public ExcelExportOptions<T> AddColumn(string fieldName, Type dataType, CellValidate validate = null, int width = 0)
        {
            this.Columns.Add(new ExportColumn()
            {
                FieldName = fieldName,
                Caption = fieldName,
                DataType = dataType,
                Validate = validate,
                Width = width
            });
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="caption"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public ExcelExportOptions<T> AddColumn(string fieldName, string caption, int width = 0)
        {
            this.Columns.Add(new ExportColumn()
            {
                FieldName = fieldName,
                Caption = caption,
                Width = width
            });
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr"></param>
        /// <returns></returns>
        private string GetPropertyName<T>(Expression<Func<T, object>> expr)
        {
            var rtn = "";
            if (expr.Body is UnaryExpression)
            {
                rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
            }
            else if (expr.Body is MemberExpression)
            {
                rtn = ((MemberExpression)expr.Body).Member.Name;
            }
            else if (expr.Body is ParameterExpression)
            {
                rtn = ((ParameterExpression)expr.Body).Type.Name;
            }
            return rtn;
        }
        private Type GetPropertyType<T>(Expression<Func<T, object>> expr)
        {
            if (expr.Body is UnaryExpression)
            {
                return ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.DeclaringType;
            }
            else if (expr.Body is MemberExpression)
            {
                return ((MemberExpression)expr.Body).Member.DeclaringType;
            }
            else if (expr.Body is ParameterExpression)
            {
                return ((ParameterExpression)expr.Body).Type;
            }
            return null;
        }
    }
}
